package com.xingkeduo.business.order.domain;

import com.netflix.client.RetryHandler;
import com.xingkeduo.business.order.remote.AdminRemoteService;
import com.xingkeduo.business.order.remote.InventoryRemoteService;
import com.xingkeduo.business.order.remote.MarketingRemoteService;
import com.xingkeduo.business.order.remote.PaymentRemoteService;
import com.xingkeduo.business.order.service.OrderRefundService;
import com.xingkeduo.business.order.service.OrderService;
import com.xingkeduo.dto.CraftsmanDTO;
import com.xingkeduo.dto.enums.StockStatusEnum;
import com.xingkeduo.dto.param.OrderRefundParamDto;
import com.xingkeduo.dto.payment.PayeeOrderResponseDto;
import com.xingkeduo.dto.payment.PayeeOrderStatus;
import com.xingkeduo.dto.payment.RefundDto;
import com.xingkeduo.pojo.enums.OrderAction;
import com.xingkeduo.pojo.enums.OrderStatus;
import com.xingkeduo.pojo.enums.RefundType;
import com.xingkeduo.pojo.query.OrderMapper;
import com.xingkeduo.pojo.query.OrderStatusLogMapper;
import com.xingkeduo.pojo.table.CraftsmanTO;
import com.xingkeduo.pojo.table.Order;
import com.xingkeduo.pojo.table.OrderRefund;
import com.xingkeduo.pojo.table.OrderStatusLog;
import com.xingkeduo.util.pojo.exception.BusinessException;
import com.xingkeduo.utils.ResponseUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;

import static com.xingkeduo.config.WechatFilter.operateIdThreadLocal;

/**
 * @author chi  2019-03-12 14:29
 **/
@Component
@Transactional
@Slf4j
public class OrderRefundDomainService {

    @Resource
    private OrderMapper orderMapper;

    @Resource
    private OrderStatusLogMapper orderStatusLogMapper;

    @Resource
    private OrderService orderService;

    @Resource
    private OrderRefundService orderRefundService;
    @Resource
    private PaymentRemoteService paymentRemoteService;
    @Resource
    private AdminRemoteService adminRemoteService;
    @Resource
    private MarketingRemoteService marketingRemoteService;
    @Resource
    private InventoryRemoteService inventoryRemoteService;


    /**
     * 用户申请退款
     *
     * @return
     */
    public boolean userRefund(OrderRefundParamDto orderRefundParamDto) {

        Order order = orderService.getOrderById(orderRefundParamDto.getId());
        order.checkRefund(RefundType.USER);


        OrderRefund orderRefund = orderRefundService.getRefundById(order.getId())
                .orElseGet(OrderRefund::new);
        orderRefund.setBackMoney(order.getPayPrice())
                .setRefundType(RefundType.USER)
                .setUserId(order.getUserId())
                .setOrderId(order.getId())
                .setSponsorTime(LocalDateTime.now())
                .setRefundReason(orderRefundParamDto.getRemark());





        OrderStatusLog orderStatusLog1 = order.covertStatus(OrderStatus.REFUND_ACCEPT, OrderAction.用户发起退款);
        orderStatusLogMapper.insert(orderStatusLog1);



        OrderStatusLog orderStatusLog = null;
        if(BigDecimal.ZERO.compareTo(order.getPayPrice())!=0){
            // 调用第三方退款接口
            RefundDto refundDto = RefundDto.builder()
                    .merchantId("1")
                    .outTradNo(order.getOrderNo())
                    .refundFee(order.getPayPrice())
                    .refundNotifyUrl("")
                    .build();
            ResponseUtils<PayeeOrderResponseDto> refund = paymentRemoteService.refund(refundDto);


            if(refund.success()){
                PayeeOrderResponseDto data = refund.getData();
                PayeeOrderStatus payeeOrderStatus = data.getPayeeOrderStatus();

                if(PayeeOrderStatus.REFUND_SUCCESS.equals(payeeOrderStatus)){

                    orderStatusLog = order.covertStatus(OrderStatus.REFUND_DONE, OrderAction.退款成功);

                }else if(PayeeOrderStatus.REFUND_FAIL.equals(payeeOrderStatus)){

                    //orderStatusLog = order.covertStatus(OrderStatus.REFUND_ERROR, OrderAction.退款失败);
                    throw new BusinessException(BusinessException.Type.DEFAULT, "退款失败请重试");
                }else if(PayeeOrderStatus.REFUND_PROCESSING.equals(payeeOrderStatus)){
                    //order.covertStatus(OrderStatus.REFUND_ACCEPT,OrderAction.用户发起退款);
                }

            }else {
                throw new BusinessException(BusinessException.Type.DEFAULT, "请重试");
            }
        }else {
            orderStatusLog = order.covertStatus(OrderStatus.REFUND_DONE, OrderAction.退款成功);
        }

        orderRefund.refund(order.getStatus());

        orderRefundService.updateOrInsert(orderRefund);
        orderMapper.updateById(order);
        if(orderStatusLog !=null){
            orderStatusLogMapper.insert(orderStatusLog);
        }

        this.refundSuccessAction(order);
        return true;
    }


    /**
     * 发型师申请退款
     *
     * @return
     */
    public boolean refundApply(OrderRefundParamDto orderRefundParamDto) {
        Order order = orderService.getOrderById(orderRefundParamDto.getId());
        order.checkRefund(RefundType.ADMIN);



        OrderRefund orderRefund = orderRefundService.getRefundById(order.getId()).orElseGet(OrderRefund::new);
        orderRefund.setBackMoney(order.getPayPrice())
                .setRefundType(RefundType.ADMIN)
                .setUserId(order.getUserId())
                .setRefundReason(orderRefundParamDto.getRemark())
                .setOrderId(order.getId())
                .setSponsorTime(LocalDateTime.now());

        if(operateIdThreadLocal.get() >0){
            CraftsmanDTO admin = adminRemoteService.getAdmin(operateIdThreadLocal.get() + "");
            orderRefund.setSponsorId(operateIdThreadLocal.get()+"");
            if(admin!=null){
                orderRefund.setSponsorName(admin.getAdminName());
            }
        }

        OrderStatusLog orderStatusLog = order.covertStatus(OrderStatus.REFUND_APPLY, OrderAction.发型师发起退款);

        orderRefund.refund(order.getStatus());
        orderRefundService.updateOrInsert(orderRefund);
        orderMapper.updateById(order);
        orderStatusLog.setRemark(orderRefundParamDto.getRemark());
        orderStatusLogMapper.insert(orderStatusLog);
        return true;
    }


    /**
     * 后台退款
     *
     * @return
     */
    public boolean refundByBackground(OrderRefundParamDto orderRefundParamDto) {
        Order order = orderService.getOrderById(orderRefundParamDto.getId());
        order.checkRefund(RefundType.BACKGROUND);

        OrderStatusLog orderStatusLog1 = order.covertStatus(OrderStatus.REFUND_ACCEPT, OrderAction.后台发起退款);
        orderMapper.updateById(order);
        orderStatusLog1.setRemark(orderRefundParamDto.getRemark());
        orderStatusLogMapper.insert(orderStatusLog1);



        OrderStatusLog orderStatusLog = null;

        if(BigDecimal.ZERO.compareTo(order.getPayPrice())!=0){
            // 调用退款接口
            RefundDto refundDto = RefundDto.builder()
                    .merchantId("1")
                    .outTradNo(order.getOrderNo())
                    .refundFee(order.getPayPrice())
                    .refundNotifyUrl("")
                    .build();
            ResponseUtils<PayeeOrderResponseDto> refund = paymentRemoteService.refund(refundDto);

            if(refund.success()){
                PayeeOrderResponseDto data = refund.getData();
                PayeeOrderStatus payeeOrderStatus = data.getPayeeOrderStatus();

                if(PayeeOrderStatus.REFUND_SUCCESS.equals(payeeOrderStatus)){

                    orderStatusLog = order.covertStatus(OrderStatus.REFUND_DONE, OrderAction.退款成功);

                }else if(PayeeOrderStatus.REFUND_FAIL.equals(payeeOrderStatus)){

                    //orderStatusLog = order.covertStatus(OrderStatus.REFUND_ERROR, OrderAction.退款失败);
                    throw new BusinessException(BusinessException.Type.DEFAULT, "退款失败请重试");
                }else if(PayeeOrderStatus.REFUND_PROCESSING.equals(payeeOrderStatus)){
                    //order.covertStatus(OrderStatus.REFUND_ACCEPT,OrderAction.用户发起退款);
                }

            }else {
                throw new BusinessException(BusinessException.Type.DEFAULT, "请重试");
            }
        }else {
            orderStatusLog = order.covertStatus(OrderStatus.REFUND_DONE, OrderAction.退款成功);
        }

        OrderRefund orderRefund = orderRefundService.getRefundById(order.getId()).orElseGet(OrderRefund::new);
        orderRefund.setBackMoney(order.getPayPrice())
                .setRefundType(RefundType.BACKGROUND)
                .setUserId(order.getUserId())
                .setRefundReason(orderRefundParamDto.getRemark())
                .setOrderId(order.getId())
                .setSponsorTime(LocalDateTime.now());

        orderStatusLogMapper.insert(orderStatusLog);

        orderRefund.refund(order.getStatus());
        orderRefundService.updateOrInsert(orderRefund);
        this.refundSuccessAction(order);

        orderMapper.updateById(order);
        return true;
    }


    /**
     * 退款检验,超时自动审核不通过
     */
    public void refundCheck(OrderRefundParamDto orderRefundParamDto) {
        Order order = orderService.getOrderById(orderRefundParamDto.getId());
        boolean b = order.checkRefund(RefundType.ADMIN);
        if (!b) {

            //超时自动审核不通过
            OrderStatusLog orderStatusLog = order.covertStatus(OrderStatus.REFUND_REGECT, OrderAction.系统退款驳回);
            orderMapper.updateById(order);
            orderStatusLogMapper.insert(orderStatusLog);

            OrderRefund orderRefund = orderRefundService.getRefundById(order.getId()).orElseGet(OrderRefund::new);
                orderRefund.setAuditingName("系统自动驳回");
            orderRefund.refund(order.getStatus());
            orderRefundService.updateOrInsert(orderRefund);


            throw new BusinessException(BusinessException.Type.DEFAULT, "此订单服务后已超90天无法退款，系统将驳回退款申请如有问题 请联系总经理");
        }
    }

    /**
     * 总经理审核通过
     *
     * @param orderRefundParamDto
     */
    public void refundAccept(OrderRefundParamDto orderRefundParamDto) {
        Order order = orderService.getOrderById(orderRefundParamDto.getId());
        boolean b = order.checkRefund(RefundType.ADMIN);
        if (!b) {
            //超时自动审核不通过
            OrderStatusLog orderStatusLog = order.covertStatus(OrderStatus.REFUND_REGECT, OrderAction.系统退款驳回);
            orderMapper.updateById(order);
            orderStatusLogMapper.insert(orderStatusLog);

            OrderRefund orderRefund = orderRefundService.getRefundById(order.getId()).orElseGet(OrderRefund::new);
            orderRefund.refund(order.getStatus());
            orderRefundService.updateOrInsert(orderRefund);

            throw new BusinessException(BusinessException.Type.DEFAULT, "此订单服务后已超90天无法退款，系统将驳回退款申请如有问题 请联系总经理");
        }

        OrderStatusLog orderStatusLog1 = order.covertStatus(OrderStatus.REFUND_ACCEPT, OrderAction.总经理审核通过);
        orderStatusLogMapper.insert(orderStatusLog1);
        orderMapper.updateById(order);



        OrderStatusLog orderStatusLog = null;
        if(BigDecimal.ZERO.compareTo(order.getPayPrice())!=0){

            // 调用第三方退款接口
            RefundDto refundDto = RefundDto.builder()
                    .merchantId("1")
                    .outTradNo(order.getOrderNo())
                    .refundFee(order.getPayPrice())
                    .refundNotifyUrl("")
                    .build();
            ResponseUtils<PayeeOrderResponseDto> refund = paymentRemoteService.refund(refundDto);

            if(refund.success()){
                PayeeOrderResponseDto data = refund.getData();
                PayeeOrderStatus payeeOrderStatus = data.getPayeeOrderStatus();

                if(PayeeOrderStatus.REFUND_SUCCESS.equals(payeeOrderStatus)){

                    orderStatusLog = order.covertStatus(OrderStatus.REFUND_DONE, OrderAction.退款成功);

                }else if(PayeeOrderStatus.REFUND_FAIL.equals(payeeOrderStatus)){

                    //orderStatusLog = order.covertStatus(OrderStatus.REFUND_ERROR, OrderAction.退款失败);
                    throw new BusinessException(BusinessException.Type.DEFAULT, "退款失败请重试");
                }

            }else {
                throw new BusinessException(BusinessException.Type.DEFAULT, "请重试");
            }

        }else {
            orderStatusLog = order.covertStatus(OrderStatus.REFUND_DONE, OrderAction.退款成功);
        }

        orderStatusLogMapper.insert(orderStatusLog);
        orderMapper.updateById(order);

        OrderRefund orderRefund = orderRefundService.getRefundById(order.getId()).orElseGet(OrderRefund::new);

        if(operateIdThreadLocal.get() >0){
            CraftsmanDTO admin = adminRemoteService.getAdmin(operateIdThreadLocal.get() + "");
            orderRefund.setAuditingId(operateIdThreadLocal.get()+"");
            if(admin!=null){
                orderRefund.setAuditingName(admin.getAdminName());
            }
        }

        orderRefund.refund(order.getStatus());
        orderRefundService.updateOrInsert(orderRefund);
        this.refundSuccessAction(order);
    }

    /**
     * 总经理退款驳回
     *
     * @param orderRefundParamDto
     */
    public void refundReject(OrderRefundParamDto orderRefundParamDto) {
        Order order = orderService.getOrderById(orderRefundParamDto.getId());

        //超时自动审核不通过
        OrderStatusLog orderStatusLog = order.covertStatus(OrderStatus.REFUND_REGECT, OrderAction.总经理退款驳回);



        OrderRefund orderRefund = orderRefundService.getRefundById(order.getId()).orElseGet(OrderRefund::new);
        if(operateIdThreadLocal.get() >0){
            CraftsmanDTO admin = adminRemoteService.getAdmin(operateIdThreadLocal.get() + "");
            orderRefund.setAuditingId(operateIdThreadLocal.get()+"")
                    .setAuditingName(admin.getAdminName());
        }
        orderRefund.reject(order.getStatus(), orderRefundParamDto.getRemark());
        orderRefundService.updateOrInsert(orderRefund);

        orderMapper.updateById(order);
        orderStatusLog.setRemark(orderRefundParamDto.getRemark());
        orderStatusLogMapper.insert(orderStatusLog);
    }


    /**
     * 微信退款到账回调
     *
     * @param payeeOrderResponseDto
     */
    public void refund(PayeeOrderResponseDto payeeOrderResponseDto) {

        try {
            Thread.sleep(1000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        String outTradeNo = payeeOrderResponseDto.getOutTradeNo();
        Order order = orderService.queryOrderByOrderNO(outTradeNo);
        OrderRefund orderRefund = orderRefundService.getRefundById(order.getId()).orElseGet(OrderRefund::new);

        OrderStatusLog orderStatusLog = order.covertStatus(OrderStatus.REFUND_DONE, OrderAction.退款成功);
        orderRefund.refund(order.getStatus());

        orderRefundService.updateOrInsert(orderRefund);
        orderMapper.updateById(order);
        orderStatusLogMapper.insert(orderStatusLog);
    }


    /**
     * 退款成功, 释放库存, 退优惠券
     * @param order
     * @return
     */
    public boolean refundSuccessAction(Order order){
        orderService.refundSuccessMessage(order);
        try {
            marketingRemoteService.refundOrder(order);
            if(StringUtils.isNotBlank(order.getAppointmentId())){
                LocalDateTime appointmentStartTime = order.getAppointmentStartTime();
                if (LocalDateTime.now().compareTo(appointmentStartTime) < 0) {
                    inventoryRemoteService.unlockInventory(order);
                } else {
                    inventoryRemoteService.updateInventory(StockStatusEnum.REFUND, order);
                }
            }
            return true;
        } catch (Exception e) {
            log.info("refundSuccessAction error:{}", e);
        }
        return false;
    }
}
